package com.nwpu.coursesupport.service.imple;

import com.nwpu.coursesupport.criteria.*;
import com.nwpu.coursesupport.entity.*;
import com.nwpu.coursesupport.entity.bean.JSONResult;
import com.nwpu.coursesupport.enumeration.*;
import com.nwpu.coursesupport.exception.BatchScorePerformanceException;
import com.nwpu.coursesupport.exception.BatchTaskAssignmentException;
import com.nwpu.coursesupport.exception.TaskSubmitBatchAddException;
import com.nwpu.coursesupport.mapper.*;
import com.nwpu.coursesupport.service.AbstractService;
import com.nwpu.coursesupport.service.TaskAssignmentService;
import com.nwpu.coursesupport.service.param.IDListParam;
import com.nwpu.coursesupport.service.param.IDParam;
import com.nwpu.coursesupport.service.param.TaskAssignmentServiceParam;
import com.nwpu.coursesupport.service.param.TaskAssignmentServiceParam.BatchParam;
import com.nwpu.coursesupport.tool.UpdateUtil;
import com.nwpu.coursesupport.view.AskList;
import com.nwpu.coursesupport.view.StudentManagerView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
@Service("taskAssignmentService")
@Transactional
public class TaskAssignmentServiceImple extends AbstractService implements TaskAssignmentService{

	@Autowired
    private TaskAssignmentMapper taskAssignmentMapper;
	@Autowired
	private TaskMapper taskMapper;
	@Autowired
	private LessonMapper lessonMapper;
	@Autowired
	private ScorePerformanceMapper scorePerformanceMapper;
	@Autowired
	private TaskSubmitResultMapper taskSubmitResultMapper;
	@Autowired
	private ClassMapper classMapper;
	@Autowired
	private ClassStudentMapper classStudentMapper;

    protected static Logger logger = LoggerFactory.getLogger(TaskAssignmentServiceImple.class);

	public JSONResult getUnAssignLesson(TaskAssignmentServiceParam.UnAssignLessonParam p){
		JSONResult rst=new JSONResult();
		rst.fail();
		if(p==null||p.getClassId()<=0||p.getTaskId()<=0){
			logger.error("参数错误");
			return rst.fail("参数错误");
		}

		LessonSearchCriteria sc=new LessonSearchCriteria();
		sc.setClassId(p.getClassId());
		sc.setType(p.getLessonType());

		List<Lesson> lessons=this.lessonMapper.find(sc);
		List<Integer> ids=new ArrayList<Integer>();
		for(Lesson l : lessons){
			ids.add(l.getId());
		}
		BatchTaskAssignmentSearchCriteria bsc=new BatchTaskAssignmentSearchCriteria();
		bsc.setTaskId(p.getTaskId());
		bsc.setLessons(ids);
		ids=this.taskAssignmentMapper.findByIds(bsc);

		Iterator<Lesson> itor=lessons.iterator();
		while(itor.hasNext()){
			Lesson l=itor.next();
			if(ids.contains(l.getId())){
				itor.remove();
			}
		}

		/*获取班级人数*/
		ClassStudentSearchCriteria classStudentSearchCriteria = new ClassStudentSearchCriteria();
		classStudentSearchCriteria.setClassId(p.getClassId());
		int numberOfStudents = this.classStudentMapper.countStudentByParam(classStudentSearchCriteria);

		rst.success();
		rst.addData("lessons",lessons);
		rst.addData("number", numberOfStudents);
		return rst;
	}

	public JSONResult batchCreate(TaskAssignmentServiceParam.BatchCreateParam p)throws BatchTaskAssignmentException,TaskSubmitBatchAddException,BatchScorePerformanceException{
		JSONResult rst=new JSONResult();
		rst.fail();

		if(p==null||p.getTaskId()==null||p.getItems()==null||p.getItems().size()<=0){
			logger.error("参数有误");
			return rst.fail("参数有误");
		}
		Task task=this.taskMapper.findById(p.getTaskId());
		if(task==null){
			logger.error("该任务不存在");
			return rst.fail("该任务不存在");
		}
		if(task.getType()==TaskType.ASKINLESSON){
			return taskInLessonBatchCreate(p);
		}else{
			return taskMainBatchCreate(p);
		}

	}

	private JSONResult taskMainBatchCreate(TaskAssignmentServiceParam.BatchCreateParam p) throws BatchTaskAssignmentException,TaskSubmitBatchAddException{
		JSONResult rst=new JSONResult();
		rst.fail();

		if(p==null||p.getTaskId()==null||p.getItems()==null||p.getItems().size()<=0){

			logger.error("参数有误");
			return rst.fail("参数有误");
		}

		Task task=this.taskMapper.findById(p.getTaskId());
		if(task==null){
			logger.error("该任务不存在");
			return rst.fail("该任务不存在");
		}
		List<Integer> lessonIds=new ArrayList<Integer>();

		for(int i=0;i<p.getItems().size();i++){
			lessonIds.add(p.getItems().get(i).getLessonId());
		}

		lessonIds=this.lessonMapper.findByIds(lessonIds);//过滤掉不存在的班级

		if(lessonIds.size() <= 0){
			logger.error("所输入课程不存在在");
			return rst.fail("所输入课程不存在在");
		}
		BatchTaskAssignmentSearchCriteria sc=new BatchTaskAssignmentSearchCriteria();
		sc.setTaskId(p.getTaskId());
		sc.setLessons(lessonIds);

		List<Integer> exitIds=this.taskAssignmentMapper.findByIds(sc);//相关课堂已经派给任务

		lessonIds.removeAll(exitIds);

		if(lessonIds.size()<=0){
			logger.error("相关任务已分配给对应课堂");
			return rst.fail("相关任务已分配给对应课堂");
		}

		int id =(int) getSession().getAttribute("id");
        String name =(String) getSession().getAttribute("name");
        RoleType roleType=(RoleType) getSession().getAttribute("roleType");
        Date date=new Date();

		//执行添加操作
		List<TaskAssignment> list=new ArrayList<TaskAssignment>();
		TaskAssignment item=null;
		Lesson lcc = null;
		for(int i=0;i<p.getItems().size();i++){
			BatchParam param=p.getItems().get(i);
			if(lessonIds.contains(param.getLessonId())){
				item=new TaskAssignment();
				item.setLessonId(param.getLessonId());
				item.setTaskId(p.getTaskId());
				item.setDeadline(param.getDeadline());
				item.setPublishDatetime(param.getPublishDatetime());///
				item.setAssignDate(date);
				item.setAssignId(id);
				item.setAssignName(name);
				item.setRoleType(roleType);
				lcc = this.lessonMapper.findById(param.getLessonId());
				item.setClassName(lcc.getClassName());
				if(param.getIsAnswerVisible()==null){
					item.setIsAnswerVisible(Status.NO);
		        }else{
		        	item.setIsAnswerVisible(param.getIsAnswerVisible());
		        }
		        if(param.getIsVisible()==null){
		        	item.setIsVisible(Status.NO);
		        }else{
		        	item.setIsVisible(param.getIsVisible());
		        }

				list.add(item);
			}
		}
		if(list.size()<=0){
			logger.error("list.size()<=0");
			return rst.success();
		}

		if(this.taskAssignmentMapper.batchSave(list)!=list.size()){
			logger.error("taskMain分配失败,并抛出异常BatchTaskAssignmentException");
			throw new BatchTaskAssignmentException();
		}
		//修改任务分配状态
		if(task.getIsQuote()!=Status.YES){
			task.setIsQuote(Status.YES);
			if(!this.taskMapper.updateQuote(task)){
				logger.error("taskMain分配失败，并抛出BatchTaskAssignmentException");
				throw new BatchTaskAssignmentException();
			}
		}

		for(TaskAssignment tma : list){
			Lesson l=this.lessonMapper.findById(tma.getLessonId());//此处有一个问题需要解决
			if(!dealTaskSubmit(tma.getId(),l.getClassId())){
	        	logger.error("taskSubmit添加失败，并抛出TaskSubmitBatchAddException");
				throw new TaskSubmitBatchAddException("批量添加提交结果失败");
	        }
		}

		rst.success();
		return rst;
	}


	private JSONResult taskInLessonBatchCreate(TaskAssignmentServiceParam.BatchCreateParam p)throws BatchTaskAssignmentException,BatchScorePerformanceException{
		JSONResult rst = new JSONResult();
        rst.fail();

        if(p==null||p.getTaskId()==null||p.getItems()==null||p.getItems().size()<=0){
        	logger.error("参数有误");
        	return rst.fail("参数有误");
        }
        Task task=this.taskMapper.findById(p.getTaskId());
        if(task==null){
        	logger.error("该任务不存在");
        	return rst.fail("该任务不存在");
        }
        Iterator<BatchParam> itor=p.getItems().iterator();
        TaskAssignmentSearchCriteria sc=null;
        List<TaskAssignment> result=new ArrayList<TaskAssignment>();
        List<Lesson> lessons=new ArrayList<Lesson>();
        TaskAssignment assign=null;
        int id =(int) getSession().getAttribute("id");
        String name=(String) getSession().getAttribute("name");
        RoleType roleType=(RoleType) getSession().getAttribute("roleType");
        Date date=new Date();
        while(itor.hasNext()){
        	BatchParam item=itor.next();
        	Lesson lesson=this.lessonMapper.findById(item.getLessonId());
            if(lesson==null){
            	continue;
            }
            sc=new TaskAssignmentSearchCriteria();
            sc.setLessonId(item.getLessonId());
            sc.setTaskId(p.getTaskId());
            List<TaskAssignment> list=this.taskAssignmentMapper.find(sc);
            if(list.size()>0){
            	continue;
            }
            if(item.getNumsOfAnswerers()<=0){
            	continue;
            }

            assign=new TaskAssignment();
            assign.setTaskId(p.getTaskId());
            assign.setLessonId(item.getLessonId());
            assign.setAssignDate(date);
            assign.setAssignId(id);
            assign.setAssignName(name);
            assign.setRoleType(roleType);
            assign.setClassName(lesson.getClassName());
            assign.setPublishDatetime(item.getPublishDatetime());
            assign.setNumsOfAnswerers(item.getNumsOfAnswerers());
            if(item.getIsVisible()==null){
            	assign.setIsVisible(Status.NO);
            }else{
            	assign.setIsVisible(item.getIsVisible());
            }

            if(item.getIsAnswerVisible()==null){
            	assign.setIsAnswerVisible(Status.NO);
            }else{
            	assign.setIsAnswerVisible(item.getIsAnswerVisible());
            }
            result.add(assign);
            lessons.add(lesson);
        }

        if(result.size()<=0){
        	logger.error("result.size()<=0");
        	return rst.success();
        }

        if(this.taskAssignmentMapper.batchSave(result)!=result.size()){
        	logger.error("taskInLesson分派失败,并抛出BatchTaskAssignmentException");
        	throw new BatchTaskAssignmentException("taskInLesson分派失败");
        }

        if(task.getIsQuote()!=Status.YES){
			task.setIsQuote(Status.YES);
			if(!this.taskMapper.updateQuote(task)){
				logger.error("修改任务状态失败，并抛出BatchTaskAssignmentException");
				throw new BatchTaskAssignmentException("修改任务状态失败");
			}
		}
        //批量添加学生
        for(int i=0;i<result.size();i++){
        	TaskAssignment item=result.get(i);
        	Lesson lesson=lessons.get(i);
        	if(!this.addScorePerformance(item,lesson.getClassId())){
            	logger.error("批量添加scorePerforce失败,并抛出BatchScorePerformanceException");
            	throw new BatchScorePerformanceException();
            }
        }

        rst.success();
        return rst;
	}


	public JSONResult create(TaskAssignmentServiceParam.CreateParam p){
        JSONResult rst = new JSONResult();
        rst.fail();

        if (p == null || p.getLessonId()<=0||p.getTaskId()<=0){
        	logger.error("参数有误");
            return rst.fail("参数有误");
        }
        Task task=this.taskMapper.findById(p.getTaskId());
        if(task==null){
        	logger.error("该任务不存在");
        	return rst.fail("该任务不存在");
        }

        Lesson lesson=this.lessonMapper.findById(p.getLessonId());
        if(lesson==null){
        	logger.error("该课堂不存在");
        	return rst.fail("该课堂不存在");
        }

        TaskAssignmentSearchCriteria sc=new TaskAssignmentSearchCriteria();
        sc.setLessonId(p.getLessonId());
        sc.setTaskId(p.getTaskId());
        List<TaskAssignment> list=this.taskAssignmentMapper.find(sc);
        if(list!=null&&list.size()>0){
        	logger.error("该任务已分配到该课堂，请勿重复操作");
        	return rst.fail("该任务已分配到该课堂，请勿重复操作");
        }

        TaskAssignment taskAssignment = p;

        int id =(int) getSession().getAttribute("id");
        String name =(String) getSession().getAttribute("name");
        RoleType roleType=(RoleType) getSession().getAttribute("roleType");
        taskAssignment.setAssignDate(new Date());
        taskAssignment.setAssignId(id);
        taskAssignment.setAssignName(name);
        taskAssignment.setRoleType(roleType);
        taskAssignment.setClassName(lesson.getClassName());
        if(p.getIsAnswerVisible()==null){
        	taskAssignment.setIsAnswerVisible(Status.NO);
        }else{
        	taskAssignment.setIsAnswerVisible(p.getIsAnswerVisible());
        }
        if(p.getIsVisible()==null){
        	taskAssignment.setIsVisible(Status.NO);
        }else{
        	taskAssignment.setIsVisible(p.getIsVisible());
        }

        if (!this.taskAssignmentMapper.save(taskAssignment)){
        	logger.error("保存失败");
            return rst.fail("保存失败");
        }
        //修改任务分配状态
        if(task.getIsQuote()!=Status.YES){
        	task.setIsQuote(Status.YES);
			if(!this.taskMapper.updateQuote(task)){
				logger.error("taskMain分配失败,并抛出TaskSubmitBatchAddException");
				throw new TaskSubmitBatchAddException();
			}
		}
        TaskType taskType=task.getType();
        if(taskType==TaskType.ASKINLESSON){
        	 if(!this.addScorePerformance(taskAssignment,lesson.getClassId())){
             	logger.error("批量添加scorePerforce失败,并抛出BatchScorePerformanceException");
             	throw new BatchScorePerformanceException();
             }
        }else if(taskType==TaskType.HOMEWORK||taskType==TaskType.LABTEST||taskType==TaskType.TESTINLESSON){
        	if(!dealTaskSubmit(taskAssignment.getId(),lesson.getClassId())){
            	throw new TaskSubmitBatchAddException("批量添加提交结果失败，并抛出TaskSubmitBatchAddException");
            }
        }

        rst.success();
        return rst;
    }

	private boolean dealTaskSubmit(int assignId,int classId){//,SubmitTaskStatus status
		StudentManagerSearchCriteria sc=new StudentManagerSearchCriteria();
		sc.setClassId(classId);
		sc.setClassType(ClassType.MANAGETEAM);
		List<StudentManagerView> list=this.lessonMapper.findStudentManagerByClassId(sc);
		if(list.size()<=0){
			return false;
		}
		Teacher t=this.classMapper.getTeacherByClassId(classId);
		List<TaskSubmitResult> result=new ArrayList<TaskSubmitResult>();
		TaskSubmitResult item=null;
		for(StudentManagerView view : list){
			item =new TaskSubmitResult();
			item.setType(TaskType.TASKMAIN);
			item.setAssignId(assignId);
			item.setAssignedId(view.getId());
			item.setRoleType(RoleType.STUDENT);
			item.setAssignedName(view.getName());
			item.setIsShare(Status.NO);
			if(view.getManagerName()==null||view.getManagerName().equals("")){//该学生尚未加入到管理班级中
				item.setReviewId(t.getId());
				item.setReviewName(t.getName());
				item.setReviewType(RoleType.TEACHER);
			}else{
				item.setReviewId(view.getManagerId());
				item.setReviewName(view.getManagerName());
				item.setReviewType(RoleType.ASSISTANT);
			}
			item.setStatus(SubmitTaskStatus.UNCOMMITTED);
			result.add(item);
		}
		if(this.taskSubmitResultMapper.batchSave(result)!=result.size()){
			return false;
		}
		return true;

	}

	private boolean addScorePerformance(TaskAssignment assign,int classId){
    	List<AskList> list=genAskStudent(classId,assign.getNumsOfAnswerers());
    	if(list.size()<=0||list.size()!=assign.getNumsOfAnswerers()){
    		return false;
    	}
    	List<ScorePerformance> result=new ArrayList<ScorePerformance>();
    	ScorePerformance item=null;
    	for(AskList s : list){
    		item=new ScorePerformance();
    		item.setAskStuId(s.getId());
    		item.setAskStuName(s.getName());
    		item.setAssignId(assign.getId());
    		item.setIsScore(Status.NO);
    		result.add(item);
    	}
    	if(this.scorePerformanceMapper.batchSave(result)!=result.size()){
    		return false;
    	}
    	return true;
    }

    /**
     * 需要有一个比较公平的算法 进行生成待提问学生名单
     * @return
     */
    private List<AskList> genAskStudent(int classId,int numbers){
    	List<Integer> studentIds=this.classMapper.findStudentByClassId(classId);
    	if(studentIds.size()<=0){
    		return new ArrayList<AskList>();
    	}

    	if(numbers>studentIds.size()){//超过了所有学生的总和
    		logger.error("提问人数过多，超出班级人数");
    		return new ArrayList<AskList>();
    	}

    	AskListSearchCriteria sc=new AskListSearchCriteria();
    	sc.setClassId(classId);
    	sc.setIds(studentIds);
    	List<AskList> list=this.scorePerformanceMapper.getAskRate(sc);
    	if(list.size()<=0){
    		return new ArrayList<AskList>();
    	}
    	//此时list的值从小到大排序
    	int index=0;
    	for(int i=0;i<list.size();i++){
    		if(list.get(i).getTime()>list.get(0).getTime()){
    			break;
    		}
    		index++;
    	}
    	List<AskList> result=new ArrayList<AskList>();
    	int flag=0;
    	if(index>=numbers){
    		flag=0;
    		Set<AskList> sets=new HashSet<AskList>(list.subList(0, index));
    		for(AskList item : sets){
    			result.add(item);
    			flag++;
    			if(flag==numbers){
    				break;
    			}
    		}
    	}else{
    		flag=0;
    		result.addAll(list.subList(0, index));
    		Set<AskList> sets=new HashSet<AskList>(list.subList(index,list.size()));
    		for(AskList item : sets){
    			result.add(item);
    			flag++;
    			if((flag+index)==numbers){
    				break;
    			}
    		}
    	}

    	return result;
    }

    public JSONResult showAnwserVisible(TaskAssignmentServiceParam.ShowAnswerParam p){
        JSONResult rst = new JSONResult();
        rst.fail();

        if (p == null || p.getId() <= 0||p.getIsVisible()==null){
        	logger.error("参数有误");
            return rst.fail("参数有误");
        }

        TaskAssignment taskmainAssignment = this.taskAssignmentMapper.findById(p.getId());
        if (taskmainAssignment == null){
        	logger.error("记录不存在或已被删除");
            return rst.fail("记录不存在或已被删除");
        }

        taskmainAssignment.setIsAnswerVisible(p.getIsVisible());
        if(!this.taskAssignmentMapper.isAnwserVisible(taskmainAssignment)){
        	logger.error("修改失败");
        	return rst.fail("修改失败");
        }
        rst.addData("taskmainAssignment", taskmainAssignment);
        rst.success();
        return rst;
    }

    public JSONResult showVisible(TaskAssignmentServiceParam.ShowAnswerParam p){
        JSONResult rst = new JSONResult();
        rst.fail();

        if (p == null || p.getId() <= 0||p.getIsVisible()==null){
        	logger.error("参数有误");
            return rst.fail("参数有误");
        }

        TaskAssignment taskAssignment = this.taskAssignmentMapper.findById(p.getId());
        if (taskAssignment == null){
        	logger.error("记录不存在或已被删除");
            return rst.fail("记录不存在或已被删除");
        }

        taskAssignment.setIsVisible(p.getIsVisible());
        if(!this.taskAssignmentMapper.isVisible(taskAssignment)){
        	logger.error("修改失败");
        	return rst.fail("修改失败");
        }

        rst.success();
        return rst;
    }


    public JSONResult updateDeadLine(TaskAssignmentServiceParam.UpdateDeadLine p){
    	JSONResult rst=new JSONResult();
    	rst.fail();

    	if(p==null||p.getId()<=0){
    		logger.error("参数有误");
    		return rst.fail("参数有误");
    	}

    	TaskAssignment assign=this.taskAssignmentMapper.findById(p.getId());

    	if(assign==null){
    		logger.error("该分配记录不存在");
    		return rst.fail("该分配记录不存在");
    	}

    	if(UpdateUtil.setValues(assign, p)>0){
    		if(!this.taskAssignmentMapper.update(assign)){
    			logger.error("修改失败");
    			return rst.fail("修改失败");
    		}
    	}

    	rst.success();
    	return rst;
    }

	@Override
	public List<Integer> findAssignmentIDByClassName(String className) {
    	return taskAssignmentMapper.findAssignmentIDByClassName(className);
	}

	@Override
	public Integer findTaskId(Integer AssignmentId) {
		return taskAssignmentMapper.findTaskId(AssignmentId);
	}

	public List<String> findClassNamesBytaskID(Integer taskID) {
		return taskAssignmentMapper.findClassNamesBytaskID(taskID);
	}

	@Override
	public Integer findAssignmentIDByClassNameandTaskID(String className, Integer taskID) {
		return taskAssignmentMapper.findAssignmentIDByClassNameandTaskID(className, taskID);
	}

	@Override
	public List<Integer> findAssignmentIDByTaskID(Integer taskID) {
		return taskAssignmentMapper.findAssignmentIDByTaskID(taskID);
	}

	public JSONResult updateAssignStatus(TaskAssignmentServiceParam.UpdateAssignStatusParam p){
    	JSONResult rst=new JSONResult();
    	rst.fail();

		System.out.println();
    	if(p==null||p.getId()<=0){
    		logger.error("参数有误");
    		return rst.fail("参数有误");
    	}

    	TaskAssignment assign=this.taskAssignmentMapper.findById(p.getId());

    	if(assign==null){
    		logger.error("该分配记录不存在");
    		return rst.fail("该分配记录不存在");
    	}

    	if(UpdateUtil.setValues(assign, p)>0){
    		if(!this.taskAssignmentMapper.updateAssignStatus(assign)){
    			logger.error("修改失败");
    			return rst.fail("修改失败");
    		}
    	}

    	rst.success();
    	return rst;
    }

    public JSONResult remove(IDParam p){
        JSONResult rst = new JSONResult();
        rst.fail();

        if (p == null || p.getId() <= 0){
        	logger.error("参数有误");
            rst.fail("参数有误");
            return rst;
        }

        TaskAssignment taskmainAssignment = this.taskAssignmentMapper.findById(p.getId());
        if (taskmainAssignment == null){
        	logger.error("记录不存在或已被删除");
            return rst.fail("记录不存在或已被删除");
        }

        if (!this.taskAssignmentMapper.delete(p.getId())){
        	logger.error("删除失败");
            return rst.fail("删除失败");
        }
        rst.addData("taskmainAssignment", taskmainAssignment);
        rst.success();
        return rst;
    }

    public JSONResult removeAll(IDListParam p){
        JSONResult rst = new JSONResult();
        rst.fail();

        if (p == null || p.getIds() == null || p.getIds().isEmpty()){
        	logger.error("参数有误");
            rst.fail("参数有误");
            return rst;
        }

        this.taskAssignmentMapper.batchDelete(p.getIds());

        rst.success();
        return rst;
    }
}
